package example.oauth.client;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import example.oauth.OAuth;
import example.oauth.OAuthAccessor;
import example.oauth.OAuthMessage;
import example.oauth.OAuthServiceProvider;
import example.oauth.OAuth.Parameter;
import example.oauth.http.HttpClient;
import example.oauth.signature.HMAC_SHA1;
import example.oauth.signature.MD5;
import example.oauth.signature.Base64;

/**
 * OAuth授权请求
 * @author tommy
 *SignatureBaseString = HttpMethod(Get/Post)&
 *		+				URL(https://open.t.qq.com/cgi-bin/request_token)&
 *						URL请求参数
 *密钥 = App Secret和Token Secret组成（中间使用&符号分隔）签名算法目前只支持HMAC-SHA1
 *Base64生成签名值
 */
public class OAuthClient {
	//private OAuthAccessor accessor;
	
	public static String TIMESTAMP = getTimeStamp();
	public static String NONCE = getNonce();
	
	public String getAccessToken(OAuthAccessor accessor,String requestToken,String tokenSecret,String verifier, String httpMethod) throws IOException {
		//String signature = getSignature(accessor,accessor.consumer.consumerSecret,tokenSecret);
		
		List<Parameter> params = OAuth.newList(OAuth.OAUTH_CONSUMER_KEY,accessor.consumer.consumerKey,
				//OAuth.OAUTH_CALLBACK,accessor.consumer.callbackURL,
				OAuth.OAUTH_TOKEN,requestToken,
        		//OAuth.OAUTH_SIGNATURE,signature,
        		OAuth.OAUTH_SIGNATURE_METHOD,OAuth.HMAC_SHA1,
        		OAuth.OAUTH_TIMESTAMP,getTimeStamp(),
        		OAuth.OAUTH_NONCE,getNonce(),
        		OAuth.OAUTH_VERIFIER,verifier,
        		OAuth.OAUTH_VERSION,"1.0");
		
	    String bodyAsParams = ""; 
	    for(int i = 0;i<params.size();i++){
	    	
	    	bodyAsParams += params.get(i).getKey()+"="+params.get(i).getValue();
	    	if(i<params.size()-1){
	    		bodyAsParams +="&";
	    	}
	    }
        //step 1.构造SignatureBaseString
        String baseString = (null==httpMethod?OAuthMessage.GET:httpMethod.toUpperCase())+"&"+
        		OAuth.encode(OAuthServiceProvider.access_token_url)+"&"+OAuth.encode(bodyAsParams);
		//step 2.构造密钥
		String secret = OAuth.encode(accessor.consumer.consumerSecret) + "&" +OAuth.encode(tokenSecret);
        String signature = sign(baseString,secret);
//System.out.println("密钥："+signature);
		
		//step 2.构造请求参数RequestToken
        String requiredParameter = bodyAsParams+"&"+OAuth.OAUTH_SIGNATURE+"="+OAuth.encode(signature);
	    
	    String access_token_url = "https://open.t.qq.com/cgi-bin/access_token";
        HttpClient http = new HttpClient();
        String status = http.execute(access_token_url, requiredParameter);
		return status;
		
		
	}
	
	/**
	 * //签名的密钥为App Secret & Request Token Secret(中间使用&分隔)
	 * @param accessor
	 * @param consumerSecret
	 * @param tokenSecret
	 * @return
	 */
	private String getSignature(OAuthAccessor accessor,String consumerSecret,String tokenSecret){
		String secret = null;
		if(null == tokenSecret){
			secret = OAuth.encode(consumerSecret)+"&";
		}else{
			secret = OAuth.encode(consumerSecret)+"&"+OAuth.encode(tokenSecret);
		}
		//secret = OAuth.encode(consumerSecret)+"&"+OAuth.encode(tokenSecret);
System.out.println("secret："+secret);
//System.out.println("tokenSecret："+tokenSecret);
        String signature = sign(getBaseString(accessor),secret);
//System.out.println("signature："+signature);
		return signature;
	}
/**
 * 获得基本String
 * @param accessor
 * @return
 */
	private String getBaseString(OAuthAccessor accessor) {
		List<Parameter> params = OAuth.newList(OAuth.OAUTH_CONSUMER_KEY,accessor.consumer.consumerKey,
	    		OAuth.OAUTH_CALLBACK,accessor.consumer.callbackURL,
	    		OAuth.OAUTH_SIGNATURE_METHOD,OAuth.HMAC_SHA1,
	    		OAuth.OAUTH_TIMESTAMP,TIMESTAMP,OAuth.OAUTH_NONCE,NONCE,
	    		OAuth.OAUTH_VERSION,"1.0");
	    String bodyAsParams = "";
	    for(int i = 0;i<params.size();i++){
	    	
	    	bodyAsParams += params.get(i).getKey()+"="+params.get(i).getValue();
	    	if(i<params.size()-1){
	    		bodyAsParams +="&";
	    	}
	    }
	    String httpMethod = "GET";
	    String access_token_url = "https://open.t.qq.com/cgi-bin/request_token";
	    //step 1.构造SignatureBaseString
	    String baseString = (null==httpMethod?OAuthMessage.GET:httpMethod.toUpperCase())+"&"+
	    		OAuth.encode(access_token_url)+"&"+OAuth.encode(bodyAsParams);
System.out.println("基本字符串："+baseString);
		return baseString;
}
//	private String getBaseString(List<Parameter> params) {
//        String bodyAsParams = "";
//        for(int i = 0;i<params.size();i++){
//        	
//        	bodyAsParams += params.get(i).getKey()+"="+params.get(i).getValue();
//        	if(i<params.size()-1){
//        		bodyAsParams +="&";
//        	}
//        }
//        String httpMethod = "GET";
//        String access_token_url = "https://open.t.qq.com/cgi-bin/access_token";
//        //step 1.构造SignatureBaseString
//        String baseString = (null==httpMethod?OAuthMessage.GET:httpMethod.toUpperCase())+"&"+
//        		OAuth.encode(access_token_url)+"&"+OAuth.encode(bodyAsParams);
//		return null;
//	}

	public Map<String,String> getRequestToken(OAuthAccessor accessor, String httpMethod)throws Exception{
		String[] results = getRequestTokenResponse(accessor,httpMethod).split("&");
		Map<String,String> params = new HashMap<String,String>();
		
		
		for(String buf:results){
			String[] val = buf.split("=");
			params.put(val[0], val[1]);
		}
		
		for (Map.Entry<String, String> param : params.entrySet()) {
			System.out.println("key： "+param.getKey()+"   vale："+param.getValue());
		}

		return params;
	}
	
	

	public String getRequestTokenResponse(OAuthAccessor accessor, String httpMethod) throws Exception{
        //accessor.accessToken = null;
        //accessor.tokenSecret = null;
        //Object accessorSecret = accessor.getProperty(OAuthConsumer.ACCESSOR_SECRET);
		List<Parameter> params = OAuth.newList(OAuth.OAUTH_CONSUMER_KEY,accessor.consumer.consumerKey,
        		OAuth.OAUTH_CALLBACK,OAuth.encode(accessor.consumer.callbackURL),
        		OAuth.OAUTH_SIGNATURE_METHOD,OAuth.HMAC_SHA1,
        		OAuth.OAUTH_TIMESTAMP,TIMESTAMP,OAuth.OAUTH_NONCE,NONCE,
        		OAuth.OAUTH_VERSION,"1.0");
        
        /*final StringBuilder baseString = new StringBuilder();
        
        if(null==httpMethod||httpMethod.equals("")){
        	baseString.append(OAuthMessage.GET+"&");
        }else{
        	baseString.append(httpMethod+"&");
        }
        baseString.append(OAuth.encode(OAuthServiceProvider.request_token_url)+"&");*/
        
        String bodyAsParams = "";
        for(int i = 0;i<params.size();i++){
        	
        	bodyAsParams += params.get(i).getKey()+"="+params.get(i).getValue();
        	if(i<params.size()-1){
        		bodyAsParams +="&";
        	}
        }
        
        //step 1.构造SignatureBaseString
        String baseString = (null==httpMethod?OAuthMessage.GET:httpMethod.toUpperCase())+"&"+
        		OAuth.encode(OAuthServiceProvider.request_token_url)+"&"+OAuth.encode(bodyAsParams);
         
//System.out.println("SignatureBaseString："+baseString);
		//step 2.构造密钥
		String secret = OAuth.encode(accessor.consumer.consumerSecret) + "&";
        String signature = sign(baseString,secret);
        //String tokenSecret = null;
//String signature = getSignature(accessor,accessor.consumer.consumerSecret,tokenSecret);
System.out.println("密钥："+signature);
		
		//step 2.构造请求参数RequestToken
        String requiredParameter = bodyAsParams+"&"+OAuth.OAUTH_SIGNATURE+"="+OAuth.encode(signature);

        HttpClient http = new HttpClient();
        String status = http.execute(OAuthServiceProvider.request_token_url, requiredParameter);
		return status;

    }
	
    public String sign(String baseString,String secret){
    	String encrypt = null;
    	 try {
			byte[] from = HMAC_SHA1.HmacSHA1Encrypt(baseString, secret);
			encrypt = Base64.encode(from);
			
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
    	 return encrypt;
    }
	public static String getNonce() {
		return new MD5().toString();
	}

	public static String getTimeStamp() {
		return String.valueOf(System.currentTimeMillis()/1000);
	}

}
